(function($){    
    $.fn.movable = (function(){      
          
        return function(config){            
            
            var $moveEle = $(this),
                $container = $(document.body),                
                startMovePoint,
                $startMoveEle;
                
            config = config || {};            
    
            var $proxy = config['proxy'] || $moveEle;
    
            $proxy.bind({            
                'mousedown' : function(e) {
                    //若正在移动中...
                    //当mouseup事件由于某种原因不能触发时，会产生这种情况, 如在scrollbar上mousedown时将不会触发mouseup.
                    if($moveEle.hasClass('moving')){                    
                        $container.trigger('mouseup');
                        return;
                    }          
                    //默认不允许通过表单元素移动.      
                    if(e.target.tagName.toLowerCase()['in']( [ 'input', 'textarea', 'select', 'button' ] )){
                        return;
                    }                
                    var movingEle = $(e.target).closest('.movable');
                    if( movingEle.length && !movingEle.hasClass('resizing') ){                 
                        startMovePoint = {
                            x : e.pageX,
                            y : e.pageY
                        };
                        $startMoveEle = $moveEle;  
                        $moveEle.addClass('moving');            
                    }
                }
            });
            
            $container.bind({
                'mousemove' : function(e) {
                    if (startMovePoint) {
                        
                        if(config['onMove']){
                            config['onMove']();
                        }
                        
                        var $this = $startMoveEle, 
                            //移动偏移量.
                            offsetX = e.pageX - startMovePoint.x,
                            offsetY = e.pageY - startMovePoint.y,
                            //当前元素坐标.
                            left = parseInt($this.css('left')), 
                            top = parseInt($this.css('top'));
    
                        startMovePoint = {
                            x : e.pageX,
                            y : e.pageY
                        };
                        
                        //容器元素的角度, 当前只处理90deg, 180deg, 270deg的情况.
                        //$this.parent().hasClass('page')  work around.
                        var containerDeg = $this.parent().hasClass('page') ? 0 : ( parseInt( $this.parent().attr('deg') ) + 36000 ) % 360;
                        if( !containerDeg ){
                            left += offsetX;
                            top += offsetY;
                        } else if( containerDeg === 90 ){
                            left += offsetY;
                            top -= offsetX;
                        } else if(containerDeg === 180){
                            left -= offsetX;
                            top -= offsetY;
                        } else {
                            left -= offsetY;
                            top += offsetX;
                        }
                        //重设元素坐标.
                        $this.css('left', left).css('top', top);
                    }
                },
                'mouseup' : function(e) {
                    startMovePoint = null;
                    $startMoveEle = null;
                    $moveEle.removeClass('moving');
                    
                    if(config['onMovingFinished']){
                        config['onMovingFinished']($moveEle);                   
                    }
                }
            });
            
            return $moveEle;
        };
    })();
    
})($);